<?php
// +----------------------------------------------------------------------
// | B5Yii2CMF V3.0 [快捷通用基础管理开发平台]
// +----------------------------------------------------------------------
// | Author: 冰舞 <357145480@qq.com>
// +----------------------------------------------------------------------
declare (strict_types=1);

namespace common\extend\plugins;

use yii\db\ActiveQuery;
use yii\db\ActiveRecord;

/**
 * Trait SoftDelete 软删除
 * 若需要直接在对应model中使用 use SoftDelete
 * 数据库表需要存在 softDeleteField定义的字段 类型为string 默认值为deleteFieldValue的值
 * 注意查询时不能使用where需要使用andWhere，否则会覆盖软删除的条件
 * @package common\extend\plugins
 */
trait SoftDelete
{
    /**
     * 删除字段
     * @return string
     */
    public static function softDeleteField(): string
    {
        return 'is_del';
    }

    /**
     * 删除时赋的值
     * @return string
     */
    public static function softIsDeleteValue(): string
    {
        return '1';
    }

    /**
     * 未删除时的值
     * @return string
     */
    public static function softNoDeleteValue(): string
    {
        return '0';
    }

    /**
     * 查询已删除数据时的操作符
     * @return string
     */
    public static function softDeleteWhereOperate(): string
    {
        return '=';
    }

    /**
     * 查询已删除数据时的操作值
     * @return string
     */
    public static function deletedWhereValue(): string
    {
        return static::softIsDeleteValue();
    }

    /**
     * 软删除方法
     * @return bool
     */
    public function softDelete(): bool
    {
        $field = static::softDeleteField();
        if ($this->isDeleted()) return false;

        $this->$field = static::softIsDeleteValue();
        if ($this->save(false, [$field])) {
            $this->afterSoftDelete();
            return true;
        }
        return false;
    }

    public function afterSoftDelete()
    {
    }

    /**
     * 批量软删除
     * @param null $condition
     * @param array $params
     * @return int
     */
    public static function softDeleteAll($condition = null, $params = []): int
    {
        $columns = [static::softDeleteField() => static::softIsDeleteValue()];
        $command = static::getDb()->createCommand();
        $command->update(static::tableName(), $columns, $condition, $params);
        return $command->execute();
    }

    /**
     * 还原软删除
     * @return bool
     */
    public function restore(): bool
    {
        $field = static::softDeleteField();
        if (!$this->isDeleted()) return false;
        $this->$field = static::softNoDeleteValue();
        return $this->save(false, [$field]);
    }

    /**
     * 查询包含软删除数据
     * @param $condition
     * @return static|null
     */
    public static function findOneWithDeleted($condition)
    {
        if (is_array($condition)) {
            return static::findWithDeleted()->where($condition)->one();
        }
        $primaryKey = static::primaryKey();
        if (isset($primaryKey[0])) return static::findWithDeleted()->where([$primaryKey[0] => $condition])->one();
        return null;
    }

    /**
     * 查询非软删除数据
     * @param string $alias
     * @return ActiveQuery
     */
    public static function find(string $alias = ''): ActiveQuery
    {
        return parent::find()->where([
            ($alias ? $alias . '.' : '') .static::softDeleteField() => static::softNoDeleteValue()
        ]);
    }


    /**
     * 查询所有包含软删除数据
     * @return ActiveQuery
     */
    public static function findWithDeleted(): ActiveQuery
    {
        return parent::find();
    }

    /**
     * 只查询软删除数据
     * @param string $alias
     * @return ActiveQuery
     */
    public static function findOnlyDeleted(string $alias = ''): ActiveQuery
    {
        return parent::find()->where([
            static::softDeleteWhereOperate(),
            ($alias ? $alias . '.' : '') . static::softDeleteField(),
            static::deletedWhereValue()
        ]);
    }

    /**
     * 判断当前实例是否是软删除数据
     * @return bool
     */
    public function isDeleted(): bool
    {
        $field = static::softDeleteField();
        $fieldValue = $this->$field ?? false;
        if ($fieldValue === false) return false;
        return $fieldValue == static::softIsDeleteValue();
    }
}
